package category

import (
	"BookStack/pkg/errors"
	"context"
)

// Service 分类领域服务接口
type Service interface {
	// CreateCategory 创建分类
	CreateCategory(ctx context.Context, category *Category) error
	// UpdateCategory 更新分类
	UpdateCategory(ctx context.Context, category *Category) error
	// DeleteCategory 删除分类
	DeleteCategory(ctx context.Context, id uint) error
	// GetCategory 获取分类
	GetCategory(ctx context.Context, id uint) (*Category, error)
	// GetCategoryBySlug 通过slug获取分类
	GetCategoryBySlug(ctx context.Context, slug string) (*Category, error)
	// ListCategories 获取分类列表
	ListCategories(ctx context.Context, params *ListParams) ([]*Category, int64, error)
	// GetCategoryTree 获取分类树
	GetCategoryTree(ctx context.Context, categoryType int) ([]*Category, error)
	// UpdateCategoryOrder 更新分类排序
	UpdateCategoryOrder(ctx context.Context, orders map[uint]int) error
	// UpdateCategoryContentCount 更新分类内容数量
	UpdateCategoryContentCount(ctx context.Context, id uint, count int64) error
	// UpdateArticleCategory 更新文章分类
	UpdateArticleCategory(ctx context.Context, articleID uint, categoryID uint) error
	// UpdateBookCategory 更新书籍分类
	UpdateBookCategory(ctx context.Context, bookID uint, categoryID uint) error
}

// service 分类服务实现
type service struct {
	repo Repository
}

// NewService 创建分类服务实例
func NewService(repo Repository) Service {
	return &service{
		repo: repo,
	}
}

// CreateCategory 创建分类
func (s *service) CreateCategory(ctx context.Context, category *Category) error {
	// 检查Slug是否已存在
	if _, err := s.repo.GetBySlug(ctx, category.Slug); err == nil {
		return errors.New(25002, "分类别名已存在")
	}

	// 如果设置了父分类，检查父分类是否存在
	if category.ParentID > 0 {
		parent, err := s.repo.GetByID(ctx, category.ParentID)
		if err != nil {
			return errors.New(25001, "父分类不存在")
		}
		if parent.Type != category.Type {
			return errors.New(25003, "父分类类型不匹配")
		}
	}

	return s.repo.Create(ctx, category)
}

// UpdateCategory 更新分类
func (s *service) UpdateCategory(ctx context.Context, category *Category) error {
	// 检查分类是否存在
	oldCategory, err := s.repo.GetByID(ctx, category.ID)
	if err != nil {
		return err
	}

	// 检查Slug是否已存在
	if oldCategory.Slug != category.Slug {
		if _, err := s.repo.GetBySlug(ctx, category.Slug); err == nil {
			return errors.New(25002, "分类别名已存在")
		}
	}

	// 如果设置了父分类，检查父分类是否存在
	if category.ParentID > 0 {
		parent, err := s.repo.GetByID(ctx, category.ParentID)
		if err != nil {
			return errors.New(25001, "父分类不存在")
		}
		if parent.Type != category.Type {
			return errors.New(25003, "父分类类型不匹配")
		}
		// 检查是否形成循环引用
		if parent.ParentID == category.ID {
			return errors.New(25004, "不能将子分类设置为父分类")
		}
	}

	return s.repo.Update(ctx, category)
}

// DeleteCategory 删除分类
func (s *service) DeleteCategory(ctx context.Context, id uint) error {
	// 检查分类是否存在
	category, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// 检查分类下是否有内容
	if category.ContentCount > 0 {
		return errors.New(25005, "分类下有内容，无法删除")
	}

	return s.repo.Delete(ctx, id)
}

// GetCategory 获取分类
func (s *service) GetCategory(ctx context.Context, id uint) (*Category, error) {
	return s.repo.GetByID(ctx, id)
}

// GetCategoryBySlug 通过slug获取分类
func (s *service) GetCategoryBySlug(ctx context.Context, slug string) (*Category, error) {
	return s.repo.GetBySlug(ctx, slug)
}

// ListCategories 获取分类列表
func (s *service) ListCategories(ctx context.Context, params *ListParams) ([]*Category, int64, error) {
	return s.repo.List(ctx, params)
}

// GetCategoryTree 获取分类树
func (s *service) GetCategoryTree(ctx context.Context, categoryType int) ([]*Category, error) {
	return s.repo.GetTree(ctx, categoryType)
}

// UpdateCategoryOrder 更新分类排序
func (s *service) UpdateCategoryOrder(ctx context.Context, orders map[uint]int) error {
	// 验证所有分类ID是否存在
	for id := range orders {
		if _, err := s.repo.GetByID(ctx, id); err != nil {
			return errors.New(25001, "分类不存在")
		}
	}
	return s.repo.UpdateOrder(ctx, orders)
}

// UpdateCategoryContentCount 更新分类内容数量
func (s *service) UpdateCategoryContentCount(ctx context.Context, id uint, count int64) error {
	// 检查分类是否存在
	if _, err := s.repo.GetByID(ctx, id); err != nil {
		return err
	}
	return s.repo.UpdateContentCount(ctx, id, count)
}

// UpdateArticleCategory 更新文章分类
func (s *service) UpdateArticleCategory(ctx context.Context, articleID uint, categoryID uint) error {
	// 检查文章是否存在
	if _, err := s.repo.GetArticleByID(ctx, articleID); err != nil {
		return err
	}

	// 检查分类是否存在
	if _, err := s.repo.GetByID(ctx, categoryID); err != nil {
		return err
	}

	return s.repo.UpdateArticleCategory(ctx, articleID, categoryID)
}

// UpdateBookCategory 更新书籍分类
func (s *service) UpdateBookCategory(ctx context.Context, bookID uint, categoryID uint) error {
	// 检查书籍是否存在
	if _, err := s.repo.GetBookByID(ctx, bookID); err != nil {
		return err
	}

	// 检查分类是否存在
	if _, err := s.repo.GetByID(ctx, categoryID); err != nil {
		return err
	}

	return s.repo.UpdateBookCategory(ctx, bookID, categoryID)
}
